package com.siemens.industrial.app;

import com.siemens.industrial.utils.DBBackupUtils;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.PreparedStatementCreator;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;

import javax.annotation.Resource;
import java.io.*;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * Created by Yipin on 2016/11/25.
 */
public class DBBackupImplementation {

    private JdbcTemplate jdbcTemplate;
    private static final String INSERT = "insert into `siemens`.`db_backup_log` (backup_time,backup_type,backup_file,backup_status) values (?,?,?,-1)";
    private static final String getOneInfo = "select * from `siemens`.`db_backup_log` where backup_id = ?";
    private static final String UPDATE = "update `siemens`.`db_backup_log` set backup_status = ? where backup_id = ?";
    private static final String FILE_PATH = DBBackupUtils.INSTANCE.filePath();
    private static final String FULL_BACKUP = DBBackupUtils.INSTANCE.fullBackupBat();
    private static final String DIFF_BACKUP = DBBackupUtils.INSTANCE.diffBackupBat();

    public void fullBackup() {
        String fileName = getTimeAsFileName() + ".sql";
        int id = saveBackupLog(fileName, "完整备份");
        if (id != 0) {
            ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", FULL_BACKUP);
            int state = runCommand(builder);
            if (findOne(id)) {
                updateBackupLog(state, id);
            } else {
                saveBackupLog(fileName, "完整备份");
            }
        }
    }

    public void diffBackup() {
        String fileName = getTimeAsFileName();
        int id = saveBackupLog(fileName, "差异备份");
        if (id != 0) {
            ProcessBuilder builder = new ProcessBuilder("cmd.exe", "/c", DIFF_BACKUP);
            if (findOne(id)) {
                int state = runCommand(builder);
                updateBackupLog(state, id);
            } else {
                saveBackupLog(fileName, "差异备份");
            }
        }
    }

    private int runCommand(ProcessBuilder builder) {
        builder.directory(new File(FILE_PATH));
        InputStream ins = null;
        try {
            Process process = builder.start();
            ins = process.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(ins, "utf8"));
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));

            String line = null;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
            while ((line = errorReader.readLine()) != null) {
                System.out.println(line);
            }
            int exitValue = process.waitFor();

            System.out.println("返回值：" + exitValue);
            reader.close();
            ins.close();
            process.getOutputStream().close();
            process.destroy();
            return exitValue;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 1;
    }

    private int saveBackupLog(String fileName, String type) {
        if (jdbcTemplate == null) {
            jdbcTemplate = DBHelper.getJdbcTemplate();
        }
        KeyHolder keyHolder = new GeneratedKeyHolder();
        int i = jdbcTemplate.update(new PreparedStatementCreator() {
            @Override
            public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {
                PreparedStatement ps = connection.prepareStatement(INSERT, new String[]{"backup_id"});
                ps.setTimestamp(1, new java.sql.Timestamp(new Date().getTime()));
                ps.setString(2, type);
                ps.setString(3, fileName);
                return ps;
            }
        }, keyHolder);

        if (i == 1) {
            return Integer.parseInt(keyHolder.getKey().toString());
        }
        return 0;
    }

    private int updateBackupLog(int status, int id) {
        return jdbcTemplate.update(UPDATE, status, id);
    }

    private boolean findOne(int id) {
        List<Map<String, Object>> list = jdbcTemplate.queryForList(getOneInfo, id);
        return (list.size() > 0);
    }

    private String getTimeAsFileName() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        return sdf.format(new Date());
    }
}
